/**
 * @author Vaarnan Drolia
 */
package data;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import core.Log;
import core.Utility;


public class Event
{
	private String name;
	private EventDateTime start;
	private int duration;
	private int priority;
	private List<String> labels;
	private String list;
	private String id;

	private EventDateTime end;
	private String description;
	private int repetition;
	private boolean ticked;
	private boolean starred;
	private boolean deadlineEvent;

	public Event() {
		Log.debug("Event: Entering default event constructor" );
		name = "";
		start = new EventDateTime();
		duration = 0;
		priority = -1;
		labels = null;
		list = null;
		end = null;
		description = null;
		//repetition = -1;
		ticked = false;
		id = null;
		starred = false;
		deadlineEvent = false;
	}

	/**
	 * event constructor
	 * @param name
	 */
	public Event(String name) {

		this();
		Log.debug("Event: Entering event constructor with name as param" );
		this.name = name;
	}

	/**
	 * event constructor
	 * @param name
	 */
	public Event(String eventName, EventDateTime startDateTime,
			EventDateTime endDateTime, int eventDuration, int stringToPriority, List<String> labels2,
			String eventList) {
		this();
		Log.debug("Event: Entering event constructor with full param list" );
		name = eventName;
		start = startDateTime;
		end = endDateTime;
		duration = eventDuration; 

		if (!endDateTime.isDefaultTime()) {
			assert(start.compareTo(end) <= 0);
			duration = Utility.millisToMins(end.getTimeInMilli() - start.getTimeInMilli());
		}
		if (duration > 0) {
			int durationMin = duration;
			end = new EventDateTime(start.getTimeInMilli());
			if (duration >= 60) {
				end.add(Calendar.HOUR, duration/60);
				durationMin = duration % 60;
			}
			end.add(Calendar.MINUTE, durationMin);
		}
		priority = stringToPriority; //TODO Implement enum
		labels = labels2;
		list = eventList;
	}

	/**
	 * 
	 * @return int the priority of the event
	 */
	public int getPriority() {
		Log.debug("Event: Entering getPriority" );
		return priority;
	}

	/**
	 * set the priority of the function
	 * @param priority
	 */
	public void setPriority(int priority) {
		Log.debug("Event: Entering setPriority" );
		this.priority = priority;
	}

	/**
	 * gets a list of all labels associated with the event
	 */
	public List<String> getLabels() {
		Log.debug("Event: Entering getLabels" );
		return labels;
	}

	/**
	 * sets all labels associated with the event
	 * @param labels
	 */
	public void setLabels(List<String> labels) {
		Log.debug("Event: Entering setLabels" );
		this.labels = labels;
	}

	/**
	 * 
	 * @return String the list that the event belongs to
	 */
	public String getList() {
		Log.debug("Event: Entering getList" );
		return list;
	}

	/**
	 * 
	 * Sets the list of an event
	 * @param list
	 */
	public void setList(String list) {
		Log.debug("Event: Entering setList" );
		this.list = list;
	}

	/**
	 * 
	 * @return the name of the event
	 */
	public String getName() {
		Log.debug("Event: Entering getName" );
		return name;
	}

	/**
	 * sets the name of the event
	 * @param name
	 */
	public void setName(String name) {
		Log.debug("Event: Entering setName" );
		this.name = name;
	}

	/**
	 * gets the description of the event
	 * @return
	 */
	public String getDescription() {
		Log.debug("Event: Entering getDescription" );
		return description;
	}

	/**
	 * sets the description of the event
	 * @param desc
	 */
	public void setDescription(String desc) {
		Log.debug("Event: Entering setDescription" );
		this.description = desc;
	}

	/**
	 * gets the start time of an event
	 * @return
	 */
	public EventDateTime getStart() {
		Log.debug("Event: Entering getStart" );
		return start;
	}

	/**
	 * sets the start time of an event
	 * @param start
	 */
	public void setStart(EventDateTime start) {
		Log.debug("Event: Entering setStart" );
		this.start = start;
	}

	/**
	 * get the end time of an event
	 * @return
	 */
	public EventDateTime getEnd() {
		Log.debug("Event: Entering getEnd" );
		return end;
	}

	/**
	 * set the end time of an event
	 * @param end
	 */
	public void setEnd(EventDateTime end) {
		Log.debug("Event: Entering setEnd" );
		this.end = end;
	}

	/**
	 * get the duration of the event
	 * @return
	 */
	public int getDuration() {
		Log.debug("Event: Entering getDuration" );
		return duration;
	}

	/**
	 * set the duration of an event
	 * @param duration
	 */
	public void setDuration(int duration) {
		Log.debug("Event: Entering setDuration" );
		this.duration = duration;
		if (duration > 0) {
			end = new EventDateTime(start.getTimeInMilli());
			end.add(Calendar.MINUTE, duration);
		}
	}

	/**
	 * true if the event is ticked
	 * @return
	 */
	public boolean getTicked() {
		Log.debug("Event: Entering getTicked" );
		return this.ticked;
	}

	/**
	 * sets the ticked value
	 * @param value
	 */
	public void setTicked(boolean value) {
		Log.debug("Event: Entering setTicked" );
		this.ticked = value;
	}

	/**
	 * toggles the ticked value
	 * @return
	 */
	public boolean toggleTicked() {
		Log.debug("Event: Entering toggleTicked" );
		if (ticked) {
			Log.warn("Event: Object was unticked by toggleTick function");
			ticked = false;
		} else {
			Log.warn("Event: Object was ticked by the toggleTick function");
			ticked = true;
		}

		return ticked;
	}
	
	/**
	 * true if event is starred
	 * @return
	 */
	public boolean getStarred() {
		Log.debug("Event: Entering getStarred" );
		return starred;
	}

	/**
	 * sets the star value of an event
	 * @param value
	 */
	public void setStarred(boolean value) {
		Log.debug("Event: Entering setStarred" );
		starred = value;
	}

	/**
	 * toggles the star value of an event
	 * @return
	 */
	public boolean toggleStarred() {
		Log.debug("Event: Entering toggleStarred" );
		if (starred) {
			Log.warn("Event: Object was unstarred by the toggleStarred function");
			starred = false;
		} else {
			Log.warn("Event: Object was starred by the toggleStarred function");
			starred = true;
		}
		return starred;
	}

	public ArrayList<String> toStringArrayList() {
		ArrayList<String> result = new ArrayList<String>();
		if (this.getName() != null) {
			result.add(this.getName());
		}
		if (!(this.getStart().getTime().isDefaultTime())) {
			int hourTime;
			int minTime;
			String time = "";
			hourTime = this.getStart().get(Calendar.HOUR);
			minTime = this.getStart().get(Calendar.MINUTE);
			if (hourTime == 0) {
				hourTime = 12;
			}
			String suffix = this.getStart().getTime().getDisplayName(Calendar.AM_PM, Calendar.SHORT).toLowerCase();
			time += hourTime;
			if (minTime > 0 && minTime < 10) {
				time+=".0" + minTime;
			} else if (minTime >= 10) {
				time += "." + minTime;
			}
			if (this.getDeadlineEvent()) {
				result.add(" by ");
			} else {
				result.add(" at ");	
			}

			result.add(time + suffix);
		}
		if(this.getDuration() > 0) {
			int min[] = Utility.minutesToHour(this.getDuration());
			result.add(" for ");

			if(min[1]==0) {
				result.add(min[0] + "hrs");
			} else if (min[0]==0) {
				result.add(min[1]+"mins");
			} else {
				result.add(min[0]+"hrs "+min[1]+"mins");
			}	
		}

		if(!(this.getStart().getDate().isDefaultTime())) {
			int day = this.getStart().get(Calendar.DAY_OF_MONTH);
			String month=this.getStart().getDate().getDisplayName(Calendar.MONTH,Calendar.SHORT);

			if (this.getDeadlineEvent()) {
				result.add(" by");
			} else {
				result.add(" on");
			}
			String dateString = " "+ day + Utility.getDaySuffix(day) + " " + month;

			int year = this.getStart().getDate().get(Calendar.YEAR);

			if (year != EventDateTime.getCurrentTime().get(Calendar.YEAR)) {
				dateString += ", "+ year;
			}

			result.add(dateString);
		}

		if (this.getLabels() != null) {
			for(String label : this.getLabels()) {
				result.add(" @");
				result.add(label);
			}
		}
		return result;
	}

	/**
	 * converts an event to string
	 */
	public String toString() {
		ArrayList<String> stringArray = toStringArrayList();
		String eventString = "";
		for (String part : stringArray) {
			eventString += part;
		}
		return eventString;
	}

	/**
	 * compares two events for equality
	 */
	public boolean equals(Object to) {
		//FIXME this function needs to be checked
		Log.debug("Event: Entering equals" );
		String thisObjString = null;
		String compareToObjString = null;
		if (to == null) {
			return false;
		}
		if (!(to instanceof Event)) {
			return false;
		}
		Event compareTo = (Event)to; 

		thisObjString = this.toString();
		compareToObjString = compareTo.toString();
		return thisObjString.equals(compareToObjString);
	}

	/**
	 * gets the event Id
	 * @return
	 */
	public String getId() {
		Log.debug("Event: Entering getId" );
		return id;
	}

	/**
	 * sets the event Id
	 * @param id
	 */
	public void setId(String id) {
		Log.debug("Event: Entering setId" );
		this.id = id;
	}

	/**
	 * true if event has a deadline
	 * @return
	 */
	public boolean getDeadlineEvent() {
		Log.debug("Event: Entering getDeadlineEvent" );
		return deadlineEvent;
	}

	/**
	 * set the deadline of an event
	 * @param newDeadline
	 */
	public void setDeadlineEvent(boolean newDeadline) {
		Log.debug("Event: Entering setDeadlineEvent" );
		this.deadlineEvent = newDeadline;
	}

}
